package com.cmc.cloud.cmclink.doc.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cmc.cloud.cmclink.doc.api.document.emums.SpecialEnum;
import com.cmc.cloud.cmclink.doc.api.document.emums.UseModuleEnum;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.AttachmentTypeErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.entity.AttachmentTypeDO;
import com.cmc.cloud.cmclink.doc.entity.GuaranteeLetterDO;
import com.cmc.cloud.cmclink.doc.mapper.AttachmentTypeMapper;
import com.cmc.cloud.cmclink.doc.mapper.GuaranteeLetterMapper;
import com.cmc.cloud.cmclink.doc.service.AttachmentTypeService;
import com.cmc.cloud.cmclink.doc.vo.attachmenttypevo.AttachmentTypeBaseVO;
import com.cmc.cloud.cmclink.doc.vo.attachmenttypevo.AttachmentTypeCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.attachmenttypevo.AttachmentTypePageReqVO;
import com.cmc.cloud.cmclink.doc.vo.attachmenttypevo.AttachmentTypeUpdateReqVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;

import cn.hutool.core.bean.BeanUtil;

/**
 * 附件类型 Service 实现类
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
public class AttachmentTypeServiceImpl implements AttachmentTypeService {

    @Resource
    private AttachmentTypeMapper attachmentTypeMapper;

    @Resource
    private GuaranteeLetterMapper guaranteeLetterMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(name = "attachmentTypeUnique", keys = {"#createReqVO.getAttatchTypeCode"})
    public void createAttachmentType(AttachmentTypeCreateReqVO createReqVO) {
        // 插入
        validateUniqueExists(createReqVO, null);
        AttachmentTypeDO attachmentType = BeanUtil.copyProperties(createReqVO, AttachmentTypeDO.class);
        attachmentTypeMapper.insert(attachmentType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(name = "attachmentTypeUnique", keys = {"#updateReqVO.getAttatchTypeCode"})
    public void updateAttachmentType(AttachmentTypeUpdateReqVO updateReqVO) {
        // 校验存在
        validateUpdateAttachmentTypeExists(updateReqVO.getId());
        validateUniqueExists(updateReqVO, updateReqVO.getId());
        // 更新
        AttachmentTypeDO updateObj = BeanUtil.copyProperties(updateReqVO, AttachmentTypeDO.class);
        attachmentTypeMapper.updateById(updateObj);
    }

    @Override
    public Boolean updateValidAttachmentType(AttachmentTypeUpdateReqVO updateReqVO) {
        AttachmentTypeDO attachmentTypeDO = attachmentTypeMapper.selectById(updateReqVO.getId());
        if (attachmentTypeDO == null) {
            throw ServiceExceptionUtil.exception(AttachmentTypeErrorCodeConstants.ATTACHMENT_TYPE_NOT_EXISTS);
        }
        return guaranteeLetterMapper.selectCount(new LambdaQueryWrapper<GuaranteeLetterDO>()
            .eq(GuaranteeLetterDO::getAttatchTypeCode, attachmentTypeDO.getAttatchTypeCode())) != 0L;
    }

    @Override
    public void deleteAttachmentType(Long id) {
        // 校验存在
        validateAttachmentTypeExists(id);
        // 删除
        attachmentTypeMapper.deleteById(id);
    }

    private void validateAttachmentTypeExists(Long id) {
        AttachmentTypeDO attachmentTypeDO = attachmentTypeMapper.selectById(id);
        if (attachmentTypeDO == null) {
            throw ServiceExceptionUtil.exception(AttachmentTypeErrorCodeConstants.ATTACHMENT_TYPE_NOT_EXISTS);
        }
        if (guaranteeLetterMapper.selectCount(new LambdaQueryWrapper<GuaranteeLetterDO>()
            .eq(GuaranteeLetterDO::getAttatchTypeCode, attachmentTypeDO.getAttatchTypeCode())) != 0L) {
            throw ServiceExceptionUtil.exception(AttachmentTypeErrorCodeConstants.ATTACHMENT_CAN_NOT_DELETE);
        }
    }

    private void validateUpdateAttachmentTypeExists(Long id) {
        AttachmentTypeDO attachmentTypeDO = attachmentTypeMapper.selectById(id);
        if (attachmentTypeDO == null) {
            throw ServiceExceptionUtil.exception(AttachmentTypeErrorCodeConstants.ATTACHMENT_TYPE_NOT_EXISTS);
        }
    }

    private void validateUniqueExists(AttachmentTypeBaseVO vo, Long id) {
        LambdaQueryWrapperX<AttachmentTypeDO> queryWrapperX = new LambdaQueryWrapperX<AttachmentTypeDO>()
            .eqIfPresent(AttachmentTypeDO::getAttatchTypeCode, vo.getAttatchTypeCode());

        if (id != null) {
            queryWrapperX.ne(AttachmentTypeDO::getId, id);
        }
        if (attachmentTypeMapper.selectCount(queryWrapperX) != 0L) {
            throw ServiceExceptionUtil.exception(AttachmentTypeErrorCodeConstants.ATTACHMENT_TYPE_EXISTED);
        }
    }

    @Override
    public AttachmentTypeDO getAttachmentType(Long id) {
        return attachmentTypeMapper.selectById(id);
    }

    @Override
    public List<AttachmentTypeDO> getAttachmentTypeList(String keyWord) {
        LambdaQueryWrapperX<AttachmentTypeDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(AttachmentTypeDO::getUseModules, UseModuleEnum.DOC);
        if (StringUtils.isNotEmpty(keyWord)) {
            queryWrapperX.and(queryWrapper -> queryWrapper.like(AttachmentTypeDO::getAttatchTypeCode, keyWord).or()
                .like(AttachmentTypeDO::getAttatchTypeCodeCn, keyWord).or()
                .like(AttachmentTypeDO::getAttatchTypeCodeEn, keyWord));
        }
        return attachmentTypeMapper.selectList(queryWrapperX);
    }

    @Override
    public List<AttachmentTypeDO> getAttachmentTypeSpcList(String keyWord) {
        LambdaQueryWrapperX<AttachmentTypeDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(AttachmentTypeDO::getUseFunctions, keyWord).eq(AttachmentTypeDO::getUseModules,
            SpecialEnum.SPC.getValue());
        return attachmentTypeMapper.selectList(queryWrapperX);
    }

    @Override
    public PageResult<AttachmentTypeDO> getAttachmentTypePage(AttachmentTypePageReqVO reqVO) {
        LambdaQueryWrapperX<AttachmentTypeDO> queryWrapperX = new LambdaQueryWrapperX<AttachmentTypeDO>()
            .eqIfPresent(AttachmentTypeDO::getAttatchTypeCode, reqVO.getAttatchTypeCode())
            .likeIfPresent(AttachmentTypeDO::getUseFunctions, reqVO.getUseFunctions())
            .likeIfPresent(AttachmentTypeDO::getUseModules, reqVO.getUseModules());
        return attachmentTypeMapper.selectPage(reqVO, queryWrapperX);
    }

    @Override
    public List<AttachmentTypeDO> getRequiredAttachList(String applyType) {
        LambdaQueryWrapperX<AttachmentTypeDO> queryWrapperX = new LambdaQueryWrapperX<>();
        queryWrapperX.eq(AttachmentTypeDO::getUseModules, SpecialEnum.SPC.getValue())
            .eq(AttachmentTypeDO::getUseFunctions, applyType).eq(AttachmentTypeDO::getRequiredStatus, true);
        return attachmentTypeMapper.selectList(queryWrapperX);
    }
}
